cmake_minimum_required(VERSION 3.1)
project(TGFX)

#set(CMAKE_VERBOSE_MAKEFILE ON)
include(../vendor_tools/vendor.cmake)

# Options for building tgfx
option(TGFX_USE_OPENGL "Allow use of OpenGL as GPU backend" ON)
option(TGFX_USE_QT "Allow build with QT frameworks." OFF)
option(TGFX_USE_SWIFTSHADER "Allow build with SwiftShader library" OFF)

if (APPLE OR WEB)
    option(TGFX_USE_FREETYPE "Allow use of embedded freetype library" OFF)
else ()
    option(TGFX_USE_FREETYPE "Allow use of embedded freetype library" ON)
endif ()

if (IOS OR WEB)
    option(TGFX_USE_WEBP_DECODE "Enable embedded WEBP decoding support" ON)
elseif (NOT ANDROID)
    option(TGFX_USE_PNG_DECODE "Enable embedded PNG decoding support" ON)
    option(TGFX_USE_PNG_ENCODE "Enable embedded PNG encoding support" ON)
    option(TGFX_USE_JPEG_DECODE "Enable embedded JPEG decoding support" ON)
    option(TGFX_USE_JPEG_ENCODE "Enable embedded JPEG encoding support" ON)
    option(TGFX_USE_WEBP_DECODE "Enable embedded WEBP decoding support" ON)
    option(TGFX_USE_WEBP_ENCODE "Enable embedded WEBP encoding support" ON)
endif ()

message("TGFX_USE_OPENGL: ${TGFX_USE_OPENGL}")
message("TGFX_USE_QT: ${TGFX_USE_QT}")
message("TGFX_USE_SWIFTSHADER: ${TGFX_USE_SWIFTSHADER}")
message("TGFX_USE_FREETYPE: ${TGFX_USE_FREETYPE}")
message("TGFX_USE_PNG_DECODE: ${TGFX_USE_PNG_DECODE}")
message("TGFX_USE_PNG_ENCODE: ${TGFX_USE_PNG_ENCODE}")
message("TGFX_USE_JPEG_DECODE: ${TGFX_USE_JPEG_DECODE}")
message("TGFX_USE_JPEG_ENCODE: ${TGFX_USE_JPEG_ENCODE}")
message("TGFX_USE_WEBP_DECODE: ${TGFX_USE_WEBP_DECODE}")
message("TGFX_USE_WEBP_ENCODE: ${TGFX_USE_WEBP_ENCODE}")

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
cmake_policy(SET CMP0063 NEW)
set(CMAKE_CXX_VISIBILITY_PRESET hidden)

if (CMAKE_CXX_COMPILER_ID MATCHES "Clang")
    add_definitions(-Werror -Wall -Wextra -Weffc++ -pedantic -Werror=return-type)
endif ()

if (MSVC)
    add_compile_options("/utf-8")
    add_compile_options(/w44251 /w44275)
    add_definitions(-DNOMINMAX -D_USE_MATH_DEFINES)
endif (MSVC)

# Sets flags
if (CMAKE_BUILD_TYPE STREQUAL "Debug")
    add_definitions(-DDEBUG)
    #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -fsanitize=address -fno-omit-frame-pointer -g -O1")
endif ()

# collects tgfx common files.
set(TGFX_INCLUDES ./ src)
file(GLOB TGFX_FILES
        src/core/*.*
        src/core/utils/*.*
        src/core/images/*.*
        src/core/vectors/*.*
        src/gpu/*.*
        src/gpu/gradients/*.*
        src/platform/*.*)

if (TGFX_USE_QT)
    set(TGFX_USE_SWIFTSHADER OFF)
endif ()

if (TGFX_USE_QT OR TGFX_USE_SWIFTSHADER)
    set(TGFX_USE_OPENGL ON)
endif ()

if (TGFX_USE_FREETYPE)
    # Freetype needs libpng
    set(TGFX_USE_PNG_DECODE ON)
endif ()

if (TGFX_USE_PNG_DECODE)
    add_definitions(-DTGFX_USE_PNG_DECODE)
    set(TGFX_USE_PNG ON)
endif ()

if (TGFX_USE_PNG_ENCODE)
    add_definitions(-DTGFX_USE_PNG_ENCODE)
    set(TGFX_USE_PNG ON)
endif ()

if (TGFX_USE_JPEG_DECODE)
    add_definitions(-DTGFX_USE_JPEG_DECODE)
    set(TGFX_USE_JPEG ON)
endif ()

if (TGFX_USE_JPEG_ENCODE)
    add_definitions(-DTGFX_USE_JPEG_ENCODE)
    set(TGFX_USE_JPEG ON)
endif ()

if (TGFX_USE_WEBP_DECODE)
    add_definitions(-DTGFX_USE_WEBP_DECODE)
    set(TGFX_USE_WEBP ON)
endif ()

if (TGFX_USE_WEBP_ENCODE)
    add_definitions(-DTGFX_USE_WEBP_ENCODE)
    set(TGFX_USE_WEBP ON)
endif ()

if (TGFX_USE_JPEG)
    list(APPEND TGFX_STATIC_VENDORS libjpeg-turbo)
    file(GLOB_RECURSE GFX_PLATFORM_FILES src/core/images/jpeg/*.*)
    list(APPEND TGFX_FILES ${GFX_PLATFORM_FILES})
    list(APPEND TGFX_INCLUDES ../third_party/out/libjpeg-turbo/${INCLUDE_ENTRY})
endif ()

if (TGFX_USE_WEBP)
    list(APPEND TGFX_STATIC_VENDORS libwebp)
    file(GLOB_RECURSE GFX_PLATFORM_FILES src/core/images/webp/*.*)
    list(APPEND TGFX_FILES ${GFX_PLATFORM_FILES})
    list(APPEND TGFX_INCLUDES ../third_party/libwebp/src)
endif ()

if (TGFX_USE_PNG)
    set(TGFX_USE_ZLIB ON)
    list(APPEND TGFX_STATIC_VENDORS libpng)
    file(GLOB_RECURSE GFX_PLATFORM_FILES src/core/images/png/*.*)
    list(APPEND TGFX_FILES ${GFX_PLATFORM_FILES})
    list(APPEND TGFX_INCLUDES ../third_party/out/libpng/${INCLUDE_ENTRY})
endif ()

if (TGFX_USE_ZLIB)
    list(APPEND TGFX_STATIC_VENDORS zlib)
endif ()

if (TGFX_USE_FREETYPE)
    add_definitions(-DTGFX_USE_FREETYPE)
    list(APPEND TGFX_STATIC_VENDORS freetype)
    file(GLOB_RECURSE GFX_PLATFORM_FILES src/core/vectors/freetype/*.*)
    list(APPEND TGFX_FILES ${GFX_PLATFORM_FILES})
    list(APPEND TGFX_INCLUDES ../third_party/freetype/include)
elseif (WEB)
    add_definitions(-DTGFX_BUILD_FOR_WEB)
    file(GLOB_RECURSE GFX_PLATFORM_FILES src/core/vectors/web/*.*)
    list(APPEND TGFX_FILES ${GFX_PLATFORM_FILES})
elseif (APPLE)
    # Uses CoreGraphics instead.
    add_definitions(-DTGFX_USE_CORE_GRAPHICS)
    file(GLOB_RECURSE GFX_PLATFORM_FILES src/core/vectors/coregraphics/*.*)
    list(APPEND TGFX_FILES ${GFX_PLATFORM_FILES})
endif ()

if (TGFX_USE_OPENGL)
    file(GLOB GFX_PLATFORM_FILES src/gpu/opengl/*.*)
    list(APPEND TGFX_FILES ${GFX_PLATFORM_FILES})
elseif (ANDROID)
    file(GLOB_RECURSE GFX_PLATFORM_FILES src/gpu/vulkan/*.*)
    list(APPEND TGFX_FILES ${GFX_PLATFORM_FILES})
elseif (APPLE)
    file(GLOB_RECURSE GFX_PLATFORM_FILES src/gpu/metal/*.*)
    list(APPEND TGFX_FILES ${GFX_PLATFORM_FILES})
    find_library(Metal_LIBS Metal REQUIRED)
    list(APPEND TGFX_PLATFORM_SHARED_LIBS ${Metal_LIBS})
endif ()

file(GLOB_RECURSE EGL_PLATFORM_FILES src/gpu/opengl/egl/*.*)

if (TGFX_USE_QT)
    # need to set the CMAKE_PREFIX_PATH to local QT installation path, for example :
    # set(CMAKE_PREFIX_PATH /Users/username/Qt5.13.0/5.13.0/clang_64/lib/cmake)
    find_package(Qt5OpenGL REQUIRED)
    find_package(Qt5Gui REQUIRED)
    find_package(Qt5Quick REQUIRED)
    list(APPEND GPU_PLATFORM_SHARED_LIBS ${Qt5OpenGL_LIBRARIES} ${Qt5Gui_LIBRARIES} ${Qt5Quick_LIBRARIES})
    list(APPEND GPU_PLATFORM_INCLUDES ${Qt5OpenGL_INCLUDE_DIRS} ${Qt5Gui_INCLUDE_DIRS} ${Qt5Quick_INCLUDE_DIRS})
    file(GLOB_RECURSE GPU_PLATFORM_FILES src/gpu/opengl/qt/*.*)
elseif (TGFX_USE_SWIFTSHADER)
    list(APPEND GPU_PLATFORM_INCLUDES ../vendor/swiftshader/include)
    file(GLOB SWIFTSHADER_LIBS ../vendor/swiftshader/${LIBRARY_ENTRY}/*${CMAKE_SHARED_LIBRARY_SUFFIX})
    list(APPEND GPU_PLATFORM_SHARED_LIBS ${SWIFTSHADER_LIBS})
    list(APPEND GPU_PLATFORM_FILES ${EGL_PLATFORM_FILES})
else ()
    set(TGFX_USE_NATIVE_GL ON)
endif ()

list(APPEND TGFX_STATIC_VENDORS pathkit)
list(APPEND TGFX_INCLUDES ../third_party/pathkit)
list(APPEND TGFX_STATIC_VENDORS skcms)
list(APPEND TGFX_INCLUDES ../third_party/skcms)

if (WEB)
    file(GLOB_RECURSE PLATFORM_FILES src/platform/web/*.*)
    list(APPEND TGFX_PLATFORM_FILES ${PLATFORM_FILES})
    if (TGFX_USE_NATIVE_GL)
        file(GLOB_RECURSE GPU_PLATFORM_FILES src/gpu/opengl/webgl/*.*)
    endif ()
elseif (IOS)
    # finds all required platform libraries.
    find_library(UIKit_LIBS UIKit REQUIRED)
    list(APPEND TGFX_PLATFORM_SHARED_LIBS ${UIKit_LIBS})
    find_library(Foundation_LIBS Foundation REQUIRED)
    list(APPEND TGFX_PLATFORM_SHARED_LIBS ${Foundation_LIBS})
    find_library(QuartzCore_LIBS QuartzCore REQUIRED)
    list(APPEND TGFX_PLATFORM_SHARED_LIBS ${QuartzCore_LIBS})
    find_library(CoreGraphics_LIBS CoreGraphics REQUIRED)
    list(APPEND TGFX_PLATFORM_SHARED_LIBS ${CoreGraphics_LIBS})
    find_library(CoreText_LIBS CoreText REQUIRED)
    list(APPEND TGFX_PLATFORM_SHARED_LIBS ${CoreText_LIBS})
    find_library(CoreMedia_LIBS CoreMedia REQUIRED)
    list(APPEND TGFX_PLATFORM_SHARED_LIBS ${CoreMedia_LIBS})
    find_library(CoreMedia_LIBS CoreMedia REQUIRED)
    list(APPEND TGFX_PLATFORM_SHARED_LIBS ${CoreMedia_LIBS})
    find_library(ImageIO_LIBS ImageIO REQUIRED)
    list(APPEND TGFX_PLATFORM_SHARED_LIBS ${ImageIO_LIBS})
    find_library(CORE_VIDEO CoreVideo)
    list(APPEND TGFX_PLATFORM_SHARED_LIBS ${CORE_VIDEO})
    find_library(ICONV_LIBRARIES NAMES iconv libiconv libiconv-2 c)
    list(APPEND TGFX_PLATFORM_SHARED_LIBS ${ICONV_LIBRARIES})

    file(GLOB_RECURSE PLATFORM_FILES src/platform/apple/*.*)
    list(APPEND TGFX_PLATFORM_FILES ${PLATFORM_FILES})

    if (TGFX_USE_NATIVE_GL)
        add_definitions(-DGL_SILENCE_DEPRECATION)
        find_library(OpenGLES_LIBS OpenGLES REQUIRED)
        list(APPEND GPU_PLATFORM_SHARED_LIBS ${OpenGLES_LIBS})
        file(GLOB_RECURSE GPU_PLATFORM_FILES src/gpu/opengl/eagl/*.*)
    endif ()
elseif (MACOS)
    # finds all required platform libraries.
    find_library(APPLICATION_SERVICES_FRAMEWORK ApplicationServices REQUIRED)
    list(APPEND TGFX_PLATFORM_SHARED_LIBS ${APPLICATION_SERVICES_FRAMEWORK})
    find_library(QUARTZ_CORE QuartzCore REQUIRED)
    list(APPEND TGFX_PLATFORM_SHARED_LIBS ${QUARTZ_CORE})
    find_library(COCOA Cocoa REQUIRED)
    list(APPEND TGFX_PLATFORM_SHARED_LIBS ${COCOA})
    find_library(FOUNDATION Foundation REQUIRED)
    list(APPEND TGFX_PLATFORM_SHARED_LIBS ${FOUNDATION})
    find_library(ICONV_LIBRARIES NAMES iconv libiconv libiconv-2 c)
    list(APPEND TGFX_PLATFORM_SHARED_LIBS ${ICONV_LIBRARIES})
    find_library(CORE_MEDIA CoreMedia)
    list(APPEND TGFX_PLATFORM_SHARED_LIBS ${CORE_MEDIA})

    file(GLOB_RECURSE PLATFORM_FILES src/platform/apple/*.*)
    list(APPEND TGFX_PLATFORM_FILES ${PLATFORM_FILES})

    if (TGFX_USE_NATIVE_GL)
        add_definitions(-DGL_SILENCE_DEPRECATION)
        find_library(OpenGL_LIBS OpenGL REQUIRED)
        list(APPEND GPU_PLATFORM_SHARED_LIBS ${OpenGL_LIBS})
        file(GLOB_RECURSE GPU_PLATFORM_FILES src/gpu/opengl/cgl/*.*)
    endif ()

elseif (ANDROID)

    find_library(LOG_LIB log)
    list(APPEND TGFX_PLATFORM_SHARED_LIBS ${LOG_LIB})
    find_library(ANDROID_LIB android)
    list(APPEND TGFX_PLATFORM_SHARED_LIBS ${ANDROID_LIB})
    find_library(JNIGRAPHICS_LIB jnigraphics)
    list(APPEND TGFX_PLATFORM_SHARED_LIBS ${JNIGRAPHICS_LIB})

    file(GLOB_RECURSE PLATFORM_FILES src/platform/android/*.*)
    list(APPEND TGFX_PLATFORM_FILES ${PLATFORM_FILES})

    if (TGFX_USE_NATIVE_GL)
        find_library(GLESV2_LIB GLESv2)
        list(APPEND GPU_PLATFORM_SHARED_LIBS ${GLESV2_LIB})
        find_library(EGL_LIB EGL)
        list(APPEND GPU_PLATFORM_SHARED_LIBS ${EGL_LIB})
        file(GLOB_RECURSE GPU_PLATFORM_FILES src/gpu/opengl/egl/*.*)
    endif ()

    # optimizes the output size
    set(CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -Wl,--gc-sections -Wl,--version-script=${CMAKE_CURRENT_SOURCE_DIR}/android/libpag/export.def")
    add_compile_options(-ffunction-sections -fdata-sections -Os -fno-exceptions -fno-rtti)

elseif (WIN32)
    find_library(Bcrypt_LIB Bcrypt)
    list(APPEND TGFX_PLATFORM_SHARED_LIBS ${Bcrypt_LIB})
    find_library(ws2_32_LIB ws2_32)
    list(APPEND TGFX_PLATFORM_SHARED_LIBS ${ws2_32_LIB})
    find_library(DWrite_LIB DWrite)
    list(APPEND TGFX_PLATFORM_STATIC_LIBS ${DWrite_LIB})

    file(GLOB_RECURSE PLATFORM_FILES src/platform/mock/*.*)
    list(APPEND TGFX_PLATFORM_FILES ${PLATFORM_FILES})

    if (TGFX_USE_NATIVE_GL)
        file(GLOB ANGLE_LIBS ../vendor/angle/${PLATFORM}/${ARCH}/*${CMAKE_STATIC_LIBRARY_SUFFIX})
        list(APPEND GPU_PLATFORM_STATIC_LIBS ${ANGLE_LIBS})
        list(APPEND GPU_PLATFORM_INCLUDES ../vendor/angle/include)
        file(GLOB_RECURSE GPU_PLATFORM_FILES src/gpu/opengl/egl/*.*)
    endif ()
elseif (CMAKE_HOST_SYSTEM_NAME MATCHES "Linux")
    find_package(Threads)
    list(APPEND TGFX_PLATFORM_SHARED_LIBS ${CMAKE_THREAD_LIBS_INIT})
    list(APPEND TGFX_PLATFORM_SHARED_LIBS dl)
    add_compile_options(-fPIC -pthread)

    file(GLOB_RECURSE PLATFORM_FILES src/platform/mock/*.*)
    list(APPEND TGFX_PLATFORM_FILES ${PLATFORM_FILES})

    if (TGFX_USE_NATIVE_GL)
        find_library(GLESV2_LIB GLESv2)
        list(APPEND GPU_PLATFORM_SHARED_LIBS ${GLESV2_LIB})
        find_library(EGL_LIB EGL)
        list(APPEND GPU_PLATFORM_SHARED_LIBS ${EGL_LIB})
        file(GLOB_RECURSE GPU_PLATFORM_FILES src/gpu/opengl/egl/*.*)
    endif ()
endif ()

add_vendor_target(TGFX STATIC_VENDORS ${TGFX_STATIC_VENDORS} SHARED_VENDORS ${TGFX_SHARED_VENDORS})
list(APPEND TGFX_PLATFORM_STATIC_LIBS ${TGFX_VENDOR_STATIC_LIBRARIES})
list(APPEND TGFX_PLATFORM_SHARED_LIBS ${TGFX_VENDOR_SHARED_LIBRARIES})

get_directory_property(HasParent PARENT_DIRECTORY)
if (HasParent)
    set(TGFX_PLATFORM_STATIC_LIBS ${TGFX_PLATFORM_STATIC_LIBS} PARENT_SCOPE)
endif ()

add_library(tgfx STATIC ${TGFX_VENDOR_TARGET} ${PLATFORM_VENDOR_TARGETS} ${TGFX_FILES} ${TGFX_PLATFORM_FILES} ${GPU_PLATFORM_FILES})
target_include_directories(tgfx PUBLIC include PRIVATE ${TGFX_INCLUDES} ${GPU_PLATFORM_INCLUDES})
merge_libraries_into(tgfx ${TGFX_STATIC_LIBS} ${TGFX_PLATFORM_STATIC_LIBS})
target_link_libraries(tgfx ${TGFX_PLATFORM_SHARED_LIBS} ${GPU_PLATFORM_SHARED_LIBS})